package com.xiaoxu.spzx.manager.service.impl;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xiaoxu.common.exception.XiaoXuException;
import com.xiaoxu.spzx.manager.mapper.SysRoleUserMapper;
import com.xiaoxu.spzx.manager.mapper.SysUserMapper;
import com.xiaoxu.spzx.manager.service.SysUserService;
import com.xiaoxu.spzx.model.dto.system.AssignRoleDto;
import com.xiaoxu.spzx.model.dto.system.LoginDto;
import com.xiaoxu.spzx.model.dto.system.SysUserDto;
import com.xiaoxu.spzx.model.entity.system.SysUser;
import com.xiaoxu.spzx.model.vo.common.ResultCodeEnum;
import com.xiaoxu.spzx.model.vo.system.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * ClassName:SysUserServiceImpl
 * Description:
 *
 * @author: 徐廷泉
 * @Create 2024/1/14 10:43
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private SysRoleUserMapper sysRoleUserMapper;
    @Override
    public LoginVo login(LoginDto loginDto) {
        //LoginDTO 包含属性 验证码codeValue  和 redis中存储验证码的key
        //分别获取前端传过来 输入的验证码  和redis存储验证码的key
        String captcha = loginDto.getCaptcha(); //输入的codeValue
        String codeKey = loginDto.getCodeKey();//key

        // 从Redis中 根据key 获取验证码
        String redisCode = redisTemplate.opsForValue().get("user:login:validatecode:" + codeKey);
        //比较输入的验证码  和  redis存储的验证码
        if(StrUtil.isEmpty(redisCode) || !StrUtil.equalsIgnoreCase(redisCode , captcha)) {
            throw new XiaoXuException(ResultCodeEnum.VALIDATECODE_ERROR) ;
            //throw new XiaoXuException(201,"验证码错误");
        }

        // 验证通过删除redis中的验证码
        redisTemplate.delete("user:login:validatecode:" + codeKey) ;

        //1 获取用户名 ，判断用户名是否存在
        String userName = loginDto.getUserName();
        //查询到了对象user
        SysUser user =  sysUserMapper.selectUserInfoByUserName(userName);

        if(user == null){
            throw new XiaoXuException(ResultCodeEnum.LOGIN_ERROR);
        }

        // 2 获取输入的密码 ，判断和数据库中的密码是否正确
        String databasePassword = user.getPassword();
        //获取前端输入的密码
        String inputPassword = loginDto.getPassword();
        //将输入的密码加密 和数据库已经加密的密码做对比
        String iputPasswordMd5 = DigestUtils.md5DigestAsHex(inputPassword.getBytes());

        if(!iputPasswordMd5.equals(databasePassword)){
            throw new XiaoXuException(ResultCodeEnum.LOGIN_ERROR);
        }

        // 3 对比成功 生成令牌 增添到redis 数据库中添加判断信息

        String token = UUID.randomUUID().toString().replaceAll("-", "");

        // 4 放到redis 中 key:token  value : 用户信息 使用JSON.toJSONString将用户实体对象转会为字符串

        redisTemplate.opsForValue().set("user:login"+token,
                JSON.toJSONString(user),
                30, TimeUnit.MINUTES);


        // 5 返回loginvo对象 也就是返回给前端的对象

        LoginVo loginVo= new LoginVo();
        loginVo.setToken(token);
        return loginVo;
    }
    /*
    * 用户信息获取的方法
    * */
    @Override
    public SysUser getUserInfo(String token) {

        String userJson = redisTemplate.opsForValue().get("user:login" + token);
        //获取用户对象返回时的json数据
        //将json字符串转换为对象 JSON.parseObject()
        //第一个参数是 参数 第二个转换的类型
        SysUser user= JSON.parseObject(userJson, SysUser.class);

        return user;
    }
    /*
    *
    * 用户退出功能*/
    @Override
    public void logout(String token) {
        // 删除redis中的数据
        redisTemplate.delete("user:login" + token);
    }



    @Override
    public PageInfo<SysUser> selectByPage(Integer pageNum, Integer pageSize, SysUserDto sysUserDto) {

        //封装条件
        PageHelper.startPage(pageNum,pageSize);

        List<SysUser> list =  sysUserMapper.selectByPage(sysUserDto);

        PageInfo<SysUser> pageInfo = new PageInfo<>(list);

        return pageInfo;
    }

    //用户添加
    @Override
    public void saveSysUser(SysUser sysUser) {

        //1 判断数据库是否已经拥有该数据？
        String userName = sysUser.getUserName();

        SysUser dbUser = sysUserMapper.selectUserInfoByUserName(userName);
        if (dbUser != null){
            //表明数据库中已经存在相同名称的数据
            throw new XiaoXuException(ResultCodeEnum.USER_NAME_IS_EXISTS);
        }

        String password = sysUser.getPassword();

        String md5password = DigestUtils.md5DigestAsHex(password.getBytes());
        //把已经加密过的密码放到数据库中
        sysUser.setPassword(md5password);

        sysUser.setStatus(1);
        sysUserMapper.save(sysUser);
    }

    @Override
    public void updateSysUser(SysUser sysUser) {

        sysUserMapper.update(sysUser);
    }

    @Override
    public void deleteById(Long userId) {
        sysUserMapper.deleteById(userId);
    }

    @Override
    public void doAssign(AssignRoleDto assignRoleDto) {
        // 删除之前的所有的用户所对应的角色数据
        sysRoleUserMapper.deleteByUserId(assignRoleDto.getUserId()) ;

        // 分配新的角色数据
        List<Long> roleIdList = assignRoleDto.getRoleIdList();
        for (Long roleId:roleIdList)
        {
            sysRoleUserMapper.doAssign(assignRoleDto.getUserId(),roleId);
        }
    }
}
